package org.example.builder;

import org.example.bean.Constants;
import org.example.bean.FiledInfo;
import org.example.bean.TableInfo;
import org.example.utils.PropertiesUtils;
import org.example.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.List;
import java.util.Map;

public class BuildServiceImpl {
    private static final Logger logger = LoggerFactory.getLogger(BuildQuery.class);
    public static void execute(TableInfo tableInfo)  {

        File folder = new File(Constants.PATH_SERVICE_IMPL);

        if(!folder.exists()) {
            folder.mkdirs();
        }

        String className = tableInfo.getBeanName()+"ServiceImpl";
        String interfaceName = tableInfo.getBeanName()+"Service";
        File poFlie = new File(folder,className + ".java ");
        OutputStream out = null;
        OutputStreamWriter outw = null;
        BufferedWriter bw = null;
        try {

            out = new FileOutputStream(poFlie);
            outw = new OutputStreamWriter(out,"utf8");
            bw = new BufferedWriter(outw);
            bw.write("package " + Constants.PACKAGE_SERVICE_IMPL + ";");
            bw.newLine();
            bw.newLine();

            String mapperName = tableInfo.getBeanName()+Constants.SUFFIX_MAPPER;
            String mapperBeanName = StringUtils.lowerCaseFirstLetter(mapperName);


            bw.write("import " + Constants.PACKAGE_PO+"." +tableInfo.getBeanName() + ";");
            bw.newLine();
            bw.write("import com.example.entity.vo.PaginationResultVO;");
            bw.newLine();
            bw.write("import com.example.enums.PageSize;");
            bw.newLine();
            bw.write("import com.example.entity.query.SimplePage;");
            bw.newLine();
            bw.write("import com.example.entity.query." + tableInfo.getBeanName() + Constants.SUFFIX_BEAN_QUERY +";");
            bw.newLine();
            bw.write("import " + Constants.PACKAGE_SERVICE+"." +interfaceName + ";");
            bw.newLine();
            bw.write("import " + Constants.PACKAGE_MAPPER+"." +tableInfo.getBeanName() + "Mapper;");
            bw.newLine();
            bw.write("import org.springframework.stereotype.Service;");

            bw.newLine();
            bw.newLine();
            bw.write("import javax.annotation.Resource;");
            bw.newLine();
            bw.write("import java.util.List;");
            bw.newLine();
            bw.newLine();


            // 类上加注释
            BuildComment.createClassComment(bw,tableInfo.getComment()+" 业务接口");


            bw.write("@Service(\"" + StringUtils.lowerCaseFirstLetter(interfaceName)+"\")");
            bw.newLine();
            bw.write("public class " + className +" implements "+interfaceName+" {");
            bw.newLine();
            bw.newLine();
            bw.write("\t@Resource");
            bw.newLine();
            //private InfoMapper<Info, InfoQuery> infoMapper;
            bw.write("\tprivate " + tableInfo.getBeanName()+"Mapper"+"<" +
                    tableInfo.getBeanName()+", "+tableInfo.getBeanName()+Constants.SUFFIX_BEAN_QUERY+"> " +mapperBeanName+";" );

            bw.newLine();
            bw.newLine();
            BuildComment.createFieldComment(bw,"根据条件查询列表");

            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic List<" + tableInfo.getBeanName()+">" + " findListByParam(" + tableInfo.getBeanParamName() + " query) {");
            bw.newLine();
            bw.write("\t\treturn this." + mapperBeanName + ".selectList(query);");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            BuildComment.createFieldComment(bw,"根据条件查询数量");
            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic Integer "+"findCountByParam(" + tableInfo.getBeanParamName() + " query) {");
            bw.newLine();
            bw.write("\t\treturn this." + mapperBeanName + ".selectCount(query);");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            BuildComment.createFieldComment(bw,"分页查询");
            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic PaginationResultVO<"+tableInfo.getBeanName()+"> findListByPage(" + tableInfo.getBeanName()+Constants.SUFFIX_BEAN_QUERY + " query) {");
            bw.newLine();
            bw.write("\t\tInteger count = this.findCountByParam(query);");
            bw.newLine();
            bw.write("\t\tInteger pageSize = query.getPageSize() == null ? PageSize.SIZE15.getSize() : query.getPageSize();");
            bw.newLine();
            bw.write("\t\tSimplePage page = new SimplePage(query.getPageNo(), count, pageSize);");
            bw.newLine();
            bw.write("\t\tquery.setSimplePage(page);");
            bw.newLine();
            bw.write("\t\tList<" + tableInfo.getBeanName()+"> list = this.findListByParam(query);");
            bw.newLine();
            bw.write("\t\tPaginationResultVO<" + tableInfo.getBeanName()+"> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);");
            bw.newLine();
            bw.write("\t\treturn result;");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            BuildComment.createFieldComment(bw,"新增");
            bw.newLine();
            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic Integer "+"add(" + tableInfo.getBeanName() + " bean) {");
            bw.newLine();
            bw.write("\t\treturn this." + mapperBeanName+".insert(bean);");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            BuildComment.createFieldComment(bw,"批量新增");


            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic Integer "+"addBatch(List<" + tableInfo.getBeanName() + "> listBean) {");
            bw.newLine();
            bw.write("\t\tif (listBean == null || listBean.isEmpty()) {");
            bw.newLine();
            bw.write("\t\t\treturn 0;");
            bw.newLine();
            bw.write("\t\t}");
            bw.newLine();
            bw.write("\t\treturn this." + mapperBeanName+".insertBatch(listBean);");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();
            bw.newLine();

            BuildComment.createFieldComment(bw,"批量新增/修改");
            bw.write("\t@Override");
            bw.newLine();
            bw.write("\tpublic Integer "+"addOrUpdateBatch(List<" + tableInfo.getBeanName() + "> listBean) {");
            bw.newLine();
            bw.write("\t\tif (listBean == null || listBean.isEmpty()) {");
            bw.newLine();
            bw.write("\t\t\treturn 0;");
            bw.newLine();
            bw.write("\t\t}");
            bw.newLine();
            bw.write("\t\treturn this." + mapperBeanName+".insertOrUpdateBatch(listBean);");
            bw.newLine();
            bw.write("\t}");
            bw.newLine();



            for ( Map.Entry<String, List<FiledInfo>> entry: tableInfo.getKeyIndexMap().entrySet()) {

                List<FiledInfo> keyFieldIndexList = entry.getValue();
                Integer index = 0;
                StringBuilder methodName = new StringBuilder();
                StringBuilder methodFieldName = new StringBuilder();
                StringBuilder methodParams = new StringBuilder();
                StringBuilder params = new StringBuilder();
                for (FiledInfo filedInfo : keyFieldIndexList) {
                    index++;
                    methodName.append(StringUtils.upperCaseFirstLetter(filedInfo.getPropertyName()));
                    methodFieldName.append(filedInfo.getFileName());
                    if (index < keyFieldIndexList.size()) {
                        methodName.append("And");

                    }
                    methodParams.append(filedInfo.getJavaType()+" " + filedInfo.getPropertyName());
                    params.append(filedInfo.getPropertyName());
                    if (index < keyFieldIndexList.size()) {
                        methodParams.append(", ");
                        params.append(", ");
                    }
                }
                bw.newLine();
                BuildComment.createFieldComment(bw,"根据"+methodName+"查询");
                bw.write("\t@Override");
                bw.newLine();
                bw.write("\tpublic "+tableInfo.getBeanName()+" get"+tableInfo.getBeanName()+"By"+methodName+" ("+methodParams+ ") {");
                bw.newLine();
                bw.write("\t\treturn this." + mapperBeanName+".selectBy"+methodName+"("+params+");");
                bw.newLine();
                bw.write("\t}");
                bw.newLine();
                bw.newLine();
                BuildComment.createFieldComment(bw,"根据"+methodName+"修改");


                bw.write("\t@Override");
                bw.newLine();
                bw.write("\tpublic Integer update"+tableInfo.getBeanName()+"By"+methodName+"("+tableInfo.getBeanName()+" bean, "+methodParams+") {");
                bw.newLine();
                bw.write("\t\treturn this." + mapperBeanName+".updateBy"+methodName+"(bean, "+params+");");

                bw.newLine();
                bw.write("\t}");
                bw.newLine();
                bw.newLine();


                BuildComment.createFieldComment(bw,"根据"+methodName+"删除");
                bw.write("\t@Override");
                bw.newLine();
                bw.write("\tpublic Integer delete"+tableInfo.getBeanName()+"By"+methodName+"("+methodParams+ ") {");
                bw.newLine();
                bw.write("\t\treturn this." + mapperBeanName+".deleteBy"+methodName+"("+params+");");

                bw.newLine();
                bw.write("\t}");
                bw.newLine();
                bw.newLine();
            }

            bw.write("}");
            bw.flush();
        } catch (Exception e) {

            logger.error("创建ServiceImpl失败！",e);
        } finally {
            if(bw != null) {
                try {
                    bw.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(outw != null) {
                try {
                    outw.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if(out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }


    }
}
